#ifndef AVALON_PIPEDMESSAGEREADER_HPP
#define AVALON_PIPEDMESSAGEREADER_HPP
#include <deque>
#include "Avalon/IO/Reader.hpp"

namespace Avalon {
namespace IO {

  /*! \class PipedMessageReader
   *  \brief Reads the contents written by a PipedMessageWriter.
   */
  class PipedMessageReader : public Reader {
    public:

      //! Constructs a PipedMessageReader.
      PipedMessageReader();

      virtual ~PipedMessageReader();

      //! Breaks the pipe.
      void Break();

      //! Breaks the pipe with an exception.
      /*!
        \param cause The exception to raise on a read operation.
      */
      void Break(const boost::exception_ptr& cause);

      virtual void Read(void* destination, int size,
        Out<Threading::Async<int> > sizeRead);

      virtual void Read(Buffer* destination, int size,
        Out<Threading::Async<int> > sizeRead);

      using Reader::Read;

    private:
      friend class PipedMessageWriter;
      boost::shared_ptr<boost::mutex> m_writeMutex;
      boost::mutex m_readMutex;
      Threading::Async<int>* m_result;
      Buffer* m_buffer;
      void* m_destination;
      int m_size;
      std::deque<BufferReader*> m_messages;
      PipedMessageWriter* m_writer;
      boost::exception_ptr m_cause;

      void Connect(PipedMessageWriter* writer);
      void InternalBreak(boost::unique_lock<boost::mutex>& readLock,
        boost::unique_lock<boost::mutex>& writeLock);
      void Write(const Buffer& message,
        boost::unique_lock<boost::mutex>& readLock,
        boost::unique_lock<boost::mutex>& writeLock);
  };
}
}

#endif // AVALON_PIPEDMESSAGEREADER_HPP
